<!-- 录音组件 -->
<template>
    <div class="record-com">
        <i v-if="isSupportRecoard()" class="icon el-icon-microphone" @click="isShow = true" />
        <i v-else class="icon el-icon-turn-off-microphone"
            @click="$message.warning('您的设备不支持录音!')" />
        <el-dialog :visible.sync="isShow" title="录音" :before-close="beforeClose" width="400px">
            <div class="record-warp">
                <div :class="'record-view'+ (audioState.isRecording?' record-view-start':'') ">
                    <el-progress class="progress" type="circle" :percentage="audioState.progress" :show-text="false"/>
                    <i class="icon el-icon-microphone" @click="startRecord"></i>
                </div>
                <div class="record-info">
                    {{millToShowText(audioState.curSec)}}s / {{millToShowText(audioState.maxSec)}}s
                </div>
                <div class="record-listen" v-show="blob != null">
                    <div class="btn-play" @click="playAlreadRecordAudio">播放录音</div>
                    <div class="btn-send" @click="sendAudio">发送录音</div>
                </div>
            </div>
        </el-dialog>
    </div>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'
import * as RecordRTC from 'recordrtc';

@Component({})
export default class RecordSoundCom extends Vue {

    $message: any
    $notify: any

    // 是否显示录音悬浮窗
    public isShow:boolean = false

    // 音频播放对象
    public audio:HTMLAudioElement = new Audio()

    // 音频流对象
    private meidaStream:MediaStream | undefined

    // 录音对象
    private recorder: any

    // 录音状态参数
    public audioState = {
        // 定义最大录音毫秒数
        maxSec: 30,
        // 是否出于录音状态
        isRecording: false,
        // 录音进度
        progress: 0,
        // 当前已经录音的毫秒数
        curSec: 0,
        // 录音计时器
        timer: 0,
        // 进度计时器
        progressTimer: 0
    }

    // 录音完成后的音频流对象
    public blob:Blob|null = null

    // 判断浏览器是否支持录音设备
    public isSupportRecoard():boolean{
        return typeof navigator.mediaDevices !== 'undefined' && 
                typeof navigator.mediaDevices.getUserMedia !== 'undefined'
    }

    // 毫秒数转显示文字
    public millToShowText(sec: number):string{
        if(sec < 10){
            return '0' + sec
        }else{
            return String(sec)
        }
    }

    // 开始录音
    public startRecord(){
        if(this.audioState.isRecording){
            // 正在录音,关闭录音
            clearTimeout(this.audioState.timer)
            this.stopRecordAudio()
        }else{
            // 清除上次录制的音频对象
            this.blob = null
            // 开始
            navigator.mediaDevices.getUserMedia({
                audio: true
            }).then(stream=>{
                this.beginRecord(stream)
            }).catch(err=>{
                this.$message.error('无法打开录音设备，可能的原因是您未允许录音权限!')
            })
        }
    }

    // 开始进行录音操作
    private beginRecord(stream:MediaStream){
        const recorder = RecordRTC(stream,{type: 'audio'});
        this.meidaStream = stream
        this.recorder = recorder
        this.audioState.isRecording = true
        // 开始录音,传入{mimeType: 'audio/mpeg'}可设置为mp3类型
        recorder.startRecording()
        // 到最大录音时间自动停止录音
        this.audioState.timer = setTimeout(()=>{
            this.stopRecordAudio()
        }, this.audioState.maxSec * 1000)
        // 设置定时器2更新录音时间，进度等信息
        this.audioState.progressTimer = setInterval(()=>{
            this.audioState.curSec += 1
            this.audioState.progress = Math.floor(this.audioState.curSec * 100 / this.audioState.maxSec) 
        }, 1000)
    }

    // 停止录音
    private stopRecordAudio(){
        const recorder:any = this.recorder;
        recorder.stopRecording((audioUrl:any)=>{
            // 设置状态为关闭
            this.audioState.isRecording = false;
            // 关闭进度监听定时器
            clearInterval(this.audioState.progressTimer);
            // 关闭音频流
            (this.meidaStream as MediaStream).getTracks().forEach(track=>{
                track.stop()
            });
            // 清除录制的状态信息
            this.audioState.progress = 0;
            this.audioState.curSec = 0;
            // 录音停止
            this.blob = recorder.getBlob()
            // 销毁对象
            recorder.destroy()
        })
    }

    // 播放已经录制完毕了的音频
    public playAlreadRecordAudio(){
        if(this.blob == null){
            // 还未有音频
            this.$message.error('您还未录制有音频，请先录制!')
            return
        }
        this.audio.src = URL.createObjectURL(this.blob);
        this.audio.play()
    }

    // 发送语音
    public sendAudio(){
        if(this.blob == null){
            // 还未有音频
            this.$message.error('您还未录制有音频，请先录制!')
            return
        }
        console.log(this.isShow)
        this.$emit('onSendAudio',this.blob)
        this.beforeClose()
    }

    // 关闭前重置状态
    public beforeClose(){
        this.audioState.isRecording = false;
        this.audioState.progress = 0;
        this.audioState.curSec = 0;
        clearTimeout(this.audioState.timer)
        clearInterval(this.audioState.progressTimer)
        this.blob = null
        this.isShow = false
    }
}
</script>

<style lang="less" scoped>
@import '../css/index.less';
.record-warp{
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    .record-round-start{
        background: #ccc;
        border-color: @theme-color;
        transition: all 0.5s;
    }
    // 打开录音时的旋转动画样式
    .record-view-start{
        background-color: blue;
        // 旋转动画
        @keyframes round {
            from{
                transform: translateX(-50%) rotate(0deg);
            }
            to{
                transform: translateX(-50%)  rotate(359deg);
            }
        }
        &::before{
            content: " ";
            width: 150px;
            height: 150px;
            transform: translateX(-50%);
            position: absolute;
            left: 50%;
            bottom: 50%;
            border-radius: 50px;
            background-color: white;
            animation: round 5s infinite linear;
        }
    }
    .record-view{
        position: relative;
        border-radius: 50%;
        overflow: hidden;
        .el-progress{
            display: block;
        }
        .icon{
            font-size: 75px;
            color: @theme-color;
            position: absolute;
            left: 50%;
            top: 50%;
            z-index: 200;
            transform: translate(-50%,-50%);
        }
    }
    .record-info{
        padding: 10px;
    }
    .record-listen{
        display: flex;
        justify-content: center;
        align-items: center;
        padding: 10px;
        width: 100%;
        & > div{
            width: 30%;
            margin: 0px 10px;
            background-color: @theme-color;
            padding: 10px;
            color: white;
            display: flex;
            justify-content: center;
            align-items: center;
            border-radius: 5px;
            transition: all 0.5s;
        }
        .btn-play{
            &:hover{
                background-color: white;
                border: 1px solid @theme-color;
                color: @theme-color;
            }
        }
        .btn-send{
            background-color: #67C23A;
            &:hover{
                background-color: white;
                border: 1px solid #67C23A;
                color: #67C23A;
            }
        }
    }
}
</style>